<template>
  <h-box v-show="visible" class="time-axis-player">
    <v-box class="player-switch-wrapper">
      <div class="mock-mark" />
      <player-switch
        v-model="playing"
        :class="{
          'is-disabled': !dataRow.length,
        }"
        color="red"
        @change="autoPlay"
      />
    </v-box>
    <i
      class="time-axis-player__close-button el-icon-error"
      @click="closeHandler"
    />
    <h-box class="time-axis-player__axis-items" size="1" flex-wrap>
      <v-box
        v-for="(cell, index) in dataRow"
        :key="index"
        class="time-axis-player__axis-item"
        :style="{
          width: `${100 / dataRow.length}%`,
        }"
        justify-content="center"
      >
        <h-box class="time-axis-player__axis-day-hours">
          <div
            v-for="hour in hourRow"
            :key="hour"
            class="time-axis-player__axis-hour-item__mark"
            :class="{
              'is-played': hourMarkerIsPlayed(cell, hour),
              'is-playing': hourMarkerIsPlaying(cell, hour),
              'is-hide': hourMarkerIsHide(cell, hour),
            }"
            :style="{
              width: `${100 / hourLabelRow.length}%`,
            }"
            @click="clickMark(cell, hour)"
          />
        </h-box>
        <h-box
          class="time-axis-player__axis-hour-labels-wrapper"
          justify-content="center"
        >
          <h-box class="time-axis-player__axis-hour-labels">
            <div
              v-for="hour in hourLabelRow"
              :key="hour"
              class="time-axis-player__axis-hour-item__label"
              :style="{
                width: `${100 / hourLabelRow.length}%`,
              }"
            >
              {{ hour }}
            </div>
          </h-box>
        </h-box>
        <div>
          {{ cell | dateFormatFilter("M/D") }}({{
            cell | dateFormatFilter("week")
          }})
        </div>
      </v-box>
    </h-box>
  </h-box>
</template>

<script>
  import dayjs from 'dayjs'

  import { createArray, createPromise, abortPromise } from '@utils'

  import HBox from '../../layout/flex-h-box'
  import VBox from '../../layout/flex-v-box'

  import playerSwitch from './player-switch.vue'

  const DEFAULTDAYRANGE = 7

  export default {
    name: 'TinyVisualUiTimeAxisPlayBar',
    components: {
      HBox,
      VBox,
      playerSwitch
    },
    props: {
      // sync
      visible: {
        type: Boolean,
        default: false
      },
      rangeStart: Date,
      rangeEnd: Date,
      selectMode: {
        type: String,
        default: 'date',
        validator (v) {
          // TODO:
          // 'year', 'month',
          return ['date'].indexOf(v) !== -1
        }
      },
      autoPlaySpeed: {
        type: Number,
        default: 2000
      }
    },
    data () {
      return {
        dataRow: [],
        hourLabelRow: createArray(7, (item, index) => 3 * (index + 1)),
        hourRow: createArray(24),
        curRangeStart: null,
        curRangeEnd: null,
        playingDate: null,
        playing: false,
        loopPlayPromise: null
      }
    },
    watch: {
      rangeStart: {
        handler () {
          this.updateDateRows()
        },
        immediate: true
      },
      rangeEnd: {
        handler () {
          this.updateDateRows()
        },
        immediate: true
      }
    },
    methods: {
      loopPlay () {
        this.loopPlayPromise = createPromise(() => {
          this.playNextHour()
          if (this.playing && !this.playingDate.isAfter(this.curRangeEnd)) {
            this.loopPlay()
          }
        }, this.autoPlaySpeed)
      },
      autoPlay (value) {
        if (value) {
          this.loopPlay()
        } else {
          this.playing = false
          abortPromise(this.loopPlayPromise)
        }
      },
      playNextHour () {
        this.playingDate = this.playingDate.add(1, 'hour')
        this.$emit('load-date', this.playingDate.toDate())
      },
      playTo (date) {
        if (date) {
          this.playingDate = dayjs(date)
        } else {
          this.playNextHour()
        }
      },
      updateDateRows () {
        this.dataRow = []
        if (this.rangeStart || this.rangeEnd) {
          let rangeStart = this.rangeStart
            ? dayjs(this.rangeStart)
            : dayjs(this.rangeEnd).subtract(DEFAULTDAYRANGE, 'day')
          rangeStart = dayjs(rangeStart.format('YYYY-MM-DD'))
          const rangeEnd = this.rangeEnd
            ? dayjs(this.rangeEnd)
            : dayjs(rangeStart).add(DEFAULTDAYRANGE + 1, 'day').subtract(1, 'second')
          this.curRangeStart = rangeStart.clone()
          if (!this.playingDate || this.playingDate?.isAfter(rangeEnd)) {
            this.playingDate = rangeStart.clone()
          }
          this.curRangeEnd = rangeEnd
          while (!rangeStart.isAfter(rangeEnd)) {
            this.dataRow.push(rangeStart)
            rangeStart = rangeStart.add(1, 'day')
          }
        }
      },
      closeHandler () {
        this.$emit('update:visible', false)
        this.autoPlay(false)
      },
      hourMarkerIsPlayed (date, hour) {
        return this.playingDate.isAfter(date.add(hour, 'hour'))
      },
      hourMarkerIsPlaying (date, hour) {
        return this.playingDate.isSame(date.add(hour, 'hour'))
      },
      hourMarkerIsHide (date, hour) {
        return !this.curRangeEnd.isAfter(date.add(hour, 'hour'))
      },
      clickMark (date, hour) {
        this.playTo(date.add(hour, 'hour'))
      }
    }
  }
</script>

<style lang="pcss">
@import "./time-axis-play-bar.pcss";
</style>
